package br.com.ps.bombertournament.game.animation;

import java.util.ArrayList;
import java.util.List;

import br.com.ps.bombertournament.game.Disposable;

/**
 * Represents a animation of the game object
 * 
 * @author Rennan Stefan Boni - rennanboni@gmail.com
 */
public class AnimationGameObject implements Disposable, Cloneable {
	
	/* Name of the animation */
	private String name;
	/* Indicate if the animation must be played all the time */
	private boolean loop;
	/* The current frame of the animation */
	private Frame currentFrame;

	/* The current time to know who is the next frame */
	private float currentTime;
	/* List of the frames */
	private List<Frame> frames;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isLoop() {
		return loop;
	}

	public void setLoop(boolean loop) {
		this.loop = loop;
	}

	public List<Frame> getFrames() {
		return frames;
	}

	public void setFrames(List<Frame> frames) {
		this.frames = frames;
	}
	
	public void dispose() {
		for (Frame frame : frames) {
			frame.dispose();
		}
	}
	
	/**
	 * Return the next frame to show.
	 * 
	 * @param deltaTime Delta time value.
	 * @return Return the next frame, can be null.
	 */
	public Frame getKeyFrame(float deltaTime) {
		Frame result = null;
		
		if (frames != null) {
			result = searchNextFrame(deltaTime);
			
			if (result == null && loop == true) {
				reset();
				result = searchNextFrame(deltaTime);
			}
		}
		
		currentFrame = result;
		
		return result;
	}
	
	/**
	 * Reset all properties preparing to be executed.
	 */
	public void reset() {
		currentTime = 0;
		
		if (frames != null) {
			for (Frame frame : frames) {
				frame.reset();
			}
		}
	}
	
	/**
	 * Return the current frame
	 * 
	 * @return Return the current frame, can be null.
	 */
	public Frame getCurrentFrame() {
		return currentFrame;
	}
	
	public boolean isFinished() {
		return currentFrame == null;
	}
	
	/**
	 * Search the next frame to show.
	 * 
	 * @param deltaTime Delta time value.
	 * @return Return the next frame, can be null.
	 */
	private Frame searchNextFrame(float deltaTime) {
		Frame result = null;
		
		// Adicionando o proximo valor do deltaTime interno
		currentTime += deltaTime;
		
		// Procurando o proximo frame a ser executado
		float totalDurationTime = 0;
		for (Frame frame : frames) {
			totalDurationTime += frame.getDuration();
			if (currentTime < totalDurationTime) {
				result = frame;
				
				break;
			}
		}
		
		return result;
	}

	@Override
	public AnimationGameObject clone() {
		try {
			AnimationGameObject result = (AnimationGameObject) super.clone();
			
			if (result.frames != null) {
				List<Frame> cloneFrames = new ArrayList<Frame>(result.frames.size());
				for (int i = 0; i < result.frames.size(); i++) {
					cloneFrames.add(i, result.frames.get(i).clone());
				}
				result.frames = cloneFrames;
			}
			
			if (result.currentFrame != null) {
				result.currentFrame = (Frame) result.currentFrame.clone();
			}
			
			return result;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}